package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.BpmnInfoMapper;
import cn.wolfcode.car.business.mapper.CarPackageAuditMapper;
import cn.wolfcode.car.business.mapper.ServiceItemMapper;
import cn.wolfcode.car.business.query.ServiceItemQuery;
import cn.wolfcode.car.business.service.IServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.Convert;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class ServiceItemServiceImpl extends ServiceImpl<ServiceItemMapper,ServiceItem> implements IServiceItemService {

    @Autowired
    private ServiceItemMapper serviceItemMapper;

    @Autowired
    private CarPackageAuditMapper carPackageAuditMapper;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private BpmnInfoMapper bpmnInfoMapper;
    @Override
    public TablePageInfo<ServiceItem> query(ServiceItemQuery qo) {
        IPage<ServiceItem> page = new Page<>(qo.getPageNum(),qo.getPageSize());
        QueryWrapper<ServiceItem> wrapper = Wrappers.<ServiceItem>query();
        wrapper.like(StringUtils.hasText(qo.getName()),"name",qo.getName());
        wrapper.eq(qo.getCarPackage()!=null,"car_package",qo.getCarPackage());
        wrapper.eq(qo.getServiceCatalog()!=null,"service_catalog",qo.getServiceCatalog());
        wrapper.eq(qo.getAuditStatus()!=null,"audit_status",qo.getAuditStatus());
        wrapper.eq(qo.getSaleStatus()!=null,"sale_status",qo.getSaleStatus());

        IPage<ServiceItem> serviceItemIPage = serviceItemMapper.selectPage(page, wrapper);
        return new TablePageInfo<ServiceItem>(super.page(serviceItemIPage,wrapper));
    }


    @Override
    public void insert(ServiceItem serviceItem) {
        //判断是否套餐
        if (ServiceItem.CARPACKAGE_NO.equals(serviceItem.getCarPackage())) {
            //不是套餐
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_NO_REQUIRED);
        }else {
            //是套餐
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        }
        //设置默认销售状态为下架
        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF);
        //设置默认时间
        serviceItem.setCreateTime(new Date());
        serviceItemMapper.insert(serviceItem);
    }

    @Override
    public ServiceItem get(Long id) {
        return serviceItemMapper.selectByPrimaryKey(id);
    }


    @Override
    public void update(ServiceItem serviceItem) {
        //前台编辑中没有状态,所以先拿对象到数据库中查
        ServiceItem item = this.get(serviceItem.getId());
        serviceItem.setAuditStatus(item.getAuditStatus());
        //判断是否上架
        //上架不能编辑
        if (ServiceItem.SALESTATUS_ON.equals(item.getSaleStatus())) {
            throw new BusinessException("请下架后再进行编辑");
        }

        //如果没有上架,不是套餐不做处理
        //如果没有上架,是套餐,而且状态是审核中,那不能编辑并抛出异常
        if (ServiceItem.CARPACKAGE_YES.equals(item.getCarPackage())
            && ServiceItem.AUDITSTATUS_AUDITING.equals(item.getAuditStatus())
        ){
            throw new BusinessException("审核中无法进行编辑");
        }
        //如果没有上架,是套餐,而且状态是审核通过,如果此时修改，应该把状态修改成初始化

            // 其他情况，原来是什么状态，应该设置什么状态.
            // 非套餐--->无需审核
            // 套餐---->初始化，重新发起

        if (ServiceItem.CARPACKAGE_NO.equals(serviceItem.getCarPackage())){
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_NO_REQUIRED);
        }else {
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        }
        //防止前台恶意对销售状态进行设置，代码中主动设置销售状态为下架状态
        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF);
        serviceItemMapper.updateByPrimaryKey(serviceItem);
    }

    @Override
    public void deleteBatch(String ids) {
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds) {
            serviceItemMapper.deleteByPrimaryKey(dictId);
        }
    }

    @Override
    public List<ServiceItem> list() {
        return serviceItemMapper.selectAll();
    }

    @Override
    public void saleOn(Long id) {
        ServiceItem serviceItem = this.get(id);
        //数据合理化
        //此条数据是否已经为上架状态
        if (ServiceItem.SALESTATUS_ON.equals(serviceItem.getSaleStatus())){
            throw new BusinessException("商品已经上架了");
        }
        //不是套餐可以直接上架(不做处理)
        //如果是套餐且审核通过不做处理,如果是套餐且审核没通过抛出异常
        if (ServiceItem.CARPACKAGE_YES.equals(serviceItem.getCarPackage())&&
        !ServiceItem.AUDITSTATUS_APPROVED.equals(serviceItem.getAuditStatus())){
            throw new BusinessException("商品审核没通过,不能上架");
        }
        //把saleStatus状态改为上架状态
        serviceItemMapper.changeSaleStatus(id,ServiceItem.SALESTATUS_ON);
    }

    @Override
    public void saleOff(Long id) {
        //把saleStatus状态改为下架状态
        serviceItemMapper.changeSaleStatus(id,ServiceItem.SALESTATUS_OFF);
    }

    @Override
    public void startAudit(Long id, Long bpmnInfoId, Long director, Long finance,String info) {
        //合理性校验
          //处于下架的服务流程才能发起审核
         //是套餐才能发起审核
        //套餐审核对象处于初始化和审核拒绝
        ServiceItem serviceItem = this.get(id);
        if (ServiceItem.SALESTATUS_ON.equals(serviceItem.getSaleStatus())
            || ServiceItem.CARPACKAGE_NO.equals(serviceItem.getCarPackage())
            || ServiceItem.AUDITSTATUS_APPROVED.equals(serviceItem.getAuditStatus())
            || ServiceItem.AUDITSTATUS_AUDITING.equals(serviceItem.getAuditStatus())
            || ServiceItem.AUDITSTATUS_NO_REQUIRED.equals(serviceItem.getAuditStatus())
        ) {
            throw new BusinessException("非法操作");
        }
        //创建carPackageAudit对象,封装数据,保存对象
        CarPackageAudit carPackageAudit = new CarPackageAudit();
        carPackageAudit.setBpmnInfoId(bpmnInfoId);//流程定义ID
        carPackageAudit.setServiceItemId(serviceItem.getId());//服务单项ID
        carPackageAudit.setServiceItemInfo(serviceItem.getInfo());//服务单项备注信息
        carPackageAudit.setServiceItemPrice(serviceItem.getDiscountPrice());//折扣价格
        carPackageAudit.setCreateTime(new Date());//创建时间
        carPackageAudit.setCreator(ShiroUtils.getUser().getUserName());//审核人
        carPackageAudit.setInfo(info);//审核备注信息
        carPackageAudit.setAuditorId(director);//审核ID
        carPackageAuditMapper.insert(carPackageAudit);//保存对象
        //启动流程实例
        //启动流程实例之前将具体的店长和财务设置进去
        Map<String, Object> map = new HashMap<>();
        map.put("director",director);
        if (finance!=null){
            map.put("finance",finance);//有可能流程不通过财务这条线路所以要判空
        }
        map.put("discountPrice",serviceItem.getDiscountPrice().longValue());
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectByPrimaryKey(bpmnInfoId);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(bpmnInfo.getActProcessKey()
                , carPackageAudit.getId().toString(),
                map);//bpmn的id的value/业务ID,负责人变量
        //更新carPackageAudit对象里的流程实例
        carPackageAuditMapper.updateByInstance(processInstance.getId(),carPackageAudit.getId());
        serviceItemMapper.changeStatus(carPackageAudit.getServiceItemId(),ServiceItem.AUDITSTATUS_AUDITING);
    }

    @Override
    public void changeAuditStatus(Long serviceItemId, Integer status) {
        carPackageAuditMapper.changeAuditStatus(serviceItemId,status);
    }

    @Override
    public void updateAuditStatus(Long serviceItemId, Integer status) {
        carPackageAuditMapper.changeAuditStatus(serviceItemId,status);
    }
}
